package com.tbit.main.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.tbit.main.constant.DaoParamConstant;
import com.tbit.main.constant.RedisConstant;
import com.tbit.main.constant.WorkOrderConstant;
import com.tbit.main.dao.core.WorkOrderDao;
import com.tbit.main.dao.core.WorkOrderFinishingDao;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.pojo.VO.WorkOrderCountRespVO;
import com.tbit.main.pojo.VO.WorkOrderQueryReqVO;
import com.tbit.main.service.*;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.main.util.LogUtil;
import com.tbit.main.util.StringUtil;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LMY
 * @create 2021-05-18 15:39
 * 工单
 */
@Service("workOrderService")
public class WorkOrderServiceImpl implements WorkOrderService {

    @Autowired
    private WorkOrderDao workOrderDao;
    @Autowired
    private RedisService redisService;
    @Autowired
    private WorkOrderFinishingService workOrderFinishingService;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private DataService dataService;
    @Autowired
    private GeoreGionService georeGionService;
    @Autowired
    private AccountUserService accountUserService;
    @Autowired
    private WorkOrderFinishingDao workOrderFinishingDao;
    @Autowired
    private GeoreMachineService georeMachineService;
    @Autowired
    private WorkOrderQuartzService workOrderQuartzService;
    @Autowired
    private PowerChangeLogService powerChangeLogService;
    @Autowired
    private RideLogService rideLogService;
    @Autowired
    private RoleService roleService;

    @Override
    public void insert(WorkOrder workOrder) {
        workOrderDao.insert(workOrder);
    }

    @Override
    public WorkOrder getByWorkOrderId(String workOrderId) {
        WorkOrder workOrder = workOrderDao.getByWorkOrderId(workOrderId);
        if (workOrder != null) {
            workOrder.parse();
        }
        return workOrder;
    }

    @Override
    public List<WorkOrder> getByWorkOrderIds(List<String> workOrderIds) {
        List<WorkOrder> workOrders = workOrderDao.getByWorkOrderIds(StringUtil.getStringListString(workOrderIds));
        workOrders.forEach(WorkOrder::parse);

        return workOrders;
    }


    @Override
    public List<WorkOrder> getByUserId(Integer accountId, AccountUser accountUser, Integer accountUserId, String startTime, String endTime,
                                       Integer state, Integer workType, Integer isValid, List<Integer> regionId, Integer assign,
                                       Integer machineType, Integer buildType, Integer pageNO, Integer rowCount, Integer locationType) {
        Map<String, Object> map = new HashMap<>();
        map.put(DaoParamConstant.accountId, accountId);
        map.put(DaoParamConstant.startTime, startTime);
        map.put(DaoParamConstant.endTime, endTime);
        map.put("state", state);
        map.put("workType", workType);
        map.put("getUserId", accountUserId);
        if (CollUtil.isEmpty(regionId)) {
            map.put("exist", "'exist'");
            regionId = georeGionService.getByAccountUserId(accountUser.getAccountUserId());
        } else {
            map.put("exist", null);
        }
        map.put("regionId", StringUtil.getListString(regionId));
        map.put("isValid", isValid);
        map.put("machineType", machineType);
        map.put("buildType", buildType);
        map.put("locationType", locationType);
        map.put("start", (pageNO - 1) * rowCount);
        map.put("rowCount", rowCount);
        LogUtil.info("分页查询已完成工单详情  参数:" + map);
        List<WorkOrder> workOrderList = workOrderDao.getByUserId(map);
        workOrderList.forEach(WorkOrder::parse);
        return workOrderList;
    }

    @Override
    public Integer getByUserIdCount(Integer accountId, AccountUser accountUser, Integer accountUserId, String startTime, String endTime,
                                    Integer state, Integer workType, Integer isValid, List<Integer> regionId, Integer assign, Integer machineType, Integer buildType, Integer locationType) {
        Map<String, Object> map = new HashMap<>();
        map.put(DaoParamConstant.accountId, accountId);
        map.put(DaoParamConstant.startTime, startTime);
        map.put(DaoParamConstant.endTime, endTime);
        map.put("state", state);
        map.put("workType", workType);
        map.put("getUserId", accountUserId);
        if (CollUtil.isEmpty(regionId)) {
            map.put("exist", "'exist'");
            regionId = georeGionService.getByAccountUserId(accountUser.getAccountUserId());
        } else {
            map.put("exist", null);
        }
        map.put("regionId", StringUtil.getListString(regionId));
        map.put("isValid", isValid);
        map.put("machineType", machineType);
        map.put("buildType", buildType);
        map.put("locationType", locationType);
        LogUtil.info("分页查询已完成工单总数 参数:" + map.toString());
        return workOrderDao.getByUserIdCount(map);
    }

    @Override
    public void updateState(String workOrderId, Integer accountUserId, String UserName, Integer businessNO, Integer state, Integer isValid) {
        Map<String, Object> map = new HashMap<>();
        if (state.equals(WorkOrderConstant.state_LQ)) {
            map.put("workOrderId", workOrderId);
            map.put("getUserId", accountUserId);
            map.put("getTime", DateTimeUtil.getNowTime());
            map.put("getUserName", UserName);
            map.put("businessNO", businessNO);
            map.put("state", state);
        } else if (state.equals(WorkOrderConstant.state_WC)) {
            map.put("workOrderId", workOrderId);
            map.put("finishTime", DateTimeUtil.getNowTime());
            map.put("state", state);
            map.put("getUserId", accountUserId);
            map.put("getUserName", UserName);
            map.put("businessNO", businessNO);
            map.put("isValid", isValid);
        } else if (state.equals(WorkOrderConstant.state_SHZ)) {
            map.put("workOrderId", workOrderId);
            map.put("finishTime", DateTimeUtil.getNowTime());
            map.put("businessNO", businessNO);
            map.put("state", state);
            map.put("isValid", isValid);
        }
        workOrderDao.updateState(map);
    }


    @Override
    public void startWork(Integer workType, AccountUser accountUser, Machine machine) {

        /***是否存在领取工单信息*/
        WorkOrderFinishing workOrderFinishing = workOrderFinishingService.getByWorkMachineIdState(workType, machine.getMachineId(), WorkOrderConstant.state_LQ);
        if (workOrderFinishing != null) {
            if (!workOrderFinishing.getGetUserId().equals(accountUser.getAccountUserId())) {
                WorkOrderConfig workOrderConfig = dataService.getWorkOrderConfig(machine.getAccountId());
                if (!workOrderConfig.getRedeploySwitch()) {
                    throw new BaseException("WorkOrder.Other.get");
                } else {

                    /**被他人接单修改*/
                    workOrderQuartzService.JPush(workOrderFinishing.getGetUserId(), WorkOrderConstant.buildType_V, workType, WorkOrderConstant.update_Work);

                    /**更新状态，转单*/
                    workOrderFinishingService.updateState(workOrderFinishing.getWorkOrderId(), accountUser.getAccountUserId(), accountUser.getName(), WorkOrderConstant.state_LQ);
                    workOrderService.updateState(workOrderFinishing.getWorkOrderId(), accountUser.getAccountUserId(), accountUser.getName(), null, WorkOrderConstant.state_LQ, null);
                }
            }
        }
    }

    @Override
    public void endWork(Integer workType, AccountUser accountUser, Integer machineId, Integer businessNO, Integer isValid, String redisKey, Integer state) {

        String workOrderId = null;
        Machine machine = dataService.getMachine(machineId);
        /**是否存在工单信息*/
        WorkOrderFinishing workOrderFinishing = workOrderFinishingService.getByMachineIdWorkType(machineId, workType, machine.getAccountId());
        if (workOrderFinishing != null) {
            workOrderId = workOrderFinishing.getWorkOrderId();

            /**删除工单缓存*/
            LogUtil.info("恢复正常，删除" + workType + "工单");

            /**完成工单*/
            workOrderService.updateState(workOrderFinishing.getWorkOrderId(), accountUser.getAccountUserId(), accountUser.getName(), businessNO, state, isValid);
            /**删除正在进行的工单*/
            workOrderFinishingService.del(workOrderFinishing.getWorkOrderId());

        } else {
            WorkOrderConfig workOrderConfig = dataService.getWorkOrderConfig(machine.getAccountId());
            if (workOrderConfig != null) {
                if ((workType.equals(WorkOrderConstant.workType_NC) && workOrderConfig.getSuperZoneMoveSwitch()) ||
                        (workType.equals(WorkOrderConstant.workType_NC) && workOrderConfig.getOutSiteMoveSwitch()) ||
                        (workType.equals(WorkOrderConstant.workType_HD) && workOrderConfig.getPowerChangeSwitch()) ||
                        (workType.equals(WorkOrderConstant.workType_WX) && workOrderConfig.getRepairSwitch())) {

                    LogUtil.info("工单，重新生成");

                    WorkOrder workOrder = new WorkOrder();
                    workOrder.setMachineId(machine.getMachineId());
                    workOrder.setMachineNO(machine.getMachineNO());
                    workOrder.setWorkType(workType);
                    workOrder.setMachineType(machine.getMachineType());
                    workOrder.setUserCode(machine.getUserCode());
                    workOrder.setFinishTime(DateTimeUtil.getNowTime());
                    GeoreMachine georeMachine = georeMachineService.getByMachineId(machine.getMachineId());
                    if (georeMachine != null) {
                        workOrder.setRegionId(georeMachine.getRegionId());
                    }

                    /**生成流水号*/
                    String serNO = StringUtil.getRideLogOrderNO();
                    workOrder.setWorkOrderId(serNO);
                    workOrder.setAccountId(machine.getAccountId());
                    workOrder.setBuildType(WorkOrderConstant.buildType_V);
                    workOrder.setBuildTime(DateTimeUtil.getNowTime());
                    workOrder.setGetUserId(accountUser.getAccountUserId());
                    workOrder.setGetTime(DateTimeUtil.getNowTime());
                    workOrder.setGetUserName(accountUser.getName());
                    workOrder.setState(state);
                    workOrder.setPriority(WorkOrderConstant.priority_Second);
                    workOrder.setIsValid(isValid);
                    workOrder.setBusinessNO(businessNO);
                    workOrderService.insert(workOrder);
                    workOrderId = serNO;
                }
            }
        }

        /**换电订单有效判断*/
        if (workType.equals(WorkOrderConstant.workType_HD)) {
            PowerChangeLog powerChangeLog = powerChangeLogService.getPowerChangeLogId(businessNO);
            String remark = powerChangeLog.getRemark();
            Integer State = WorkOrderConstant.state_WC;
            AccountConfig accountConfig = dataService.getAccountConfig(machine.getAccountId());
            if (isValid != 0) {

                /**查询记录*/
                List<PowerChangeLog> powerChangeLogs = new LinkedList<>();
                List<RideLog> rideLogs = new LinkedList<>();
                if ((accountConfig.getRide() != null && accountConfig != null) || (accountConfig.getRideDistance() != null && accountConfig.getRideDistance() != 0)) {
                    powerChangeLogs = powerChangeLogService.getByMachineIdTime(machine.getMachineId(), null, 1);
                    if (powerChangeLogs != null && powerChangeLogs.size() > isValid) {
                        rideLogs = rideLogService.getMachineIdStartTime(machine.getMachineId(), powerChangeLogs.get(isValid).getChangeTime(), null);
                    } else {
                        rideLogs = rideLogService.getMachineIdStartTime(machine.getMachineId(), null, DateTimeUtil.getNowTime());
                    }
                }

                /**判断订单时间*/
                if (accountConfig.getRideTime() != null && accountConfig.getRideTime() != 0) {
                    State = WorkOrderConstant.state_SHZ;
                }

                /**判断两个工单内有订单*/
                if (accountConfig.getRide() != null && accountConfig.getRide() != 0 && isValid.equals(1)) {
                    if (rideLogs != null && rideLogs.size() > 0) {
                        isValid = 1;
                        List<String> rideLogOrder = rideLogs.stream().map(RideLog::getOrderNO).collect(Collectors.toList());
                        remark = remark + WorkOrderConstant.sys_ride_isValid + ":" + rideLogOrder.toString();
                    } else {
                        isValid = 0;
                        remark = remark + WorkOrderConstant.sys_ride_Valid;
                    }
                }

                /**判断订单间隔时间*/
                if (accountConfig.getLogTime() != null && accountConfig.getLogTime() != 0 && isValid.equals(1)) {
                    //LogUtil.info("配置："+accountConfig.toString());

                    List<PowerChangeLog> powerChangeLogList = powerChangeLogService.getByMachineIdTime(machine.getMachineId(), DateTimeUtil.getMinsAgo(accountConfig.getLogTime()), 1);
                    //LogUtil.info("powerChangeLogList："+powerChangeLogList.toString());
                    if (isValid.equals(0)) {
                        if (powerChangeLogList != null && powerChangeLogList.size() > 0) {
                            isValid = 0;
                            remark = remark + WorkOrderConstant.sys_logTime_Valid;
                        } else {
                            isValid = 1;
                            remark = remark + WorkOrderConstant.sys_logTime_isValid;
                        }
                    } else {
                        if (powerChangeLogList != null && powerChangeLogList.size() >= 2) {
                            isValid = 0;
                            remark = remark + WorkOrderConstant.sys_logTime_Valid;
                        } else {
                            isValid = 1;
                            remark = remark + WorkOrderConstant.sys_logTime_isValid;
                        }
                    }

                }

                if (accountConfig.getRideDistance() != null && accountConfig.getRideDistance() != 0 && isValid.equals(1)) {
                    double distanceCount = 0;
                    if (rideLogs != null && rideLogs.size() > 0) {
                        for (RideLog rideLog : rideLogs) {
                            distanceCount = distanceCount + rideLog.getMileage() * 1000;
                        }
                        if (distanceCount >= accountConfig.getRideDistance()) {
                            isValid = 1;
                            remark = remark + distanceCount + WorkOrderConstant.sys_rideDistance_isValid;
                        } else {
                            isValid = 0;
                            remark = remark + distanceCount + WorkOrderConstant.sys_rideDistance_Valid;
                        }
                    } else {
                        isValid = 0;
                        remark = remark + distanceCount + WorkOrderConstant.sys_rideDistance_Valid;
                    }
                }
            }

            WorkOrder workOrderDB = workOrderDao.getByWorkOrderId(workOrderId);
            if (workOrderDB != null) {
                workOrderDB.parse();
            }
            /**无效，直接结束*/
            if (State.equals(WorkOrderConstant.state_WC) || isValid.equals(0)) {
                redisService.del(RedisConstant.REDIS_TER_BATTERY_CHANGE_RIDE + machine.getMachineNO());
                /**二级缓存*/
                redisService.del(RedisConstant.REDIS_TER_BIKE_BATTERY_CHANGE_RIDE_MAP, machine.getMachineNO());

                powerChangeLogService.update(businessNO, null, isValid, remark, DateTimeUtil.getNowTime());

                State = WorkOrderConstant.state_WC;
                LogUtil.info("无效或者完结");
            } else {

                PowerChangeRedis powerChangeRedis = new PowerChangeRedis();
                powerChangeRedis.setPowerChangeId(businessNO);
                powerChangeRedis.setWorkOrderId(workOrderId);
                powerChangeRedis.setRideTime(accountConfig.getRideTime());
                powerChangeRedis.setTime(DateTimeUtil.getNowTime());

                List<PowerChangeRedis> powerChangeList = new LinkedList<>();

                /**判断是否存在审核中*/
                String powerChangeRedisList = redisService.get(RedisConstant.REDIS_TER_BATTERY_CHANGE_RIDE + machine.getMachineNO());
                if (powerChangeRedisList != null) {
                    //List<PowerChangeRedis> powerChangeLogs = JSONObject.parseObject(powerChangeRedisList, List.class);
                    List<PowerChangeRedis> powerChangeLogs = new LinkedList<>();
                    try {
                        powerChangeLogs = JSON.parseArray(powerChangeRedisList, PowerChangeRedis.class);
                    } catch (JSONException e) {
                        redisService.del(RedisConstant.REDIS_TER_BATTERY_CHANGE_RIDE + machine.getMachineNO());
                    }


                    if (powerChangeLogs != null && powerChangeLogs.size() > 0) {
                        for (PowerChangeRedis powerChangeLog1 : powerChangeLogs) {
                            powerChangeList.add(powerChangeLog1);
                        }
                    }

                }
                powerChangeList.add(powerChangeRedis);


                /**订单判断缓存*/
                redisService.add(RedisConstant.REDIS_TER_BATTERY_CHANGE_RIDE + machine.getMachineNO(), JSONObject.toJSONString(powerChangeList), 60 * 60 * accountConfig.getRideTime() + 60 * 20);
                /**二级缓存*/
                redisService.set(RedisConstant.REDIS_TER_BIKE_BATTERY_CHANGE_RIDE_MAP, machine.getMachineNO(), String.valueOf(System.currentTimeMillis()));

                isValid = null;
                powerChangeLogService.update(businessNO, null, WorkOrderConstant.aduit, remark, DateTimeUtil.getNowTime());
                LogUtil.info("审核中");
            }

            if (workOrderDB != null) {
                WorkOrder workOrder = new WorkOrder();
                workOrder.setWorkOrderId(workOrderId);
                workOrder.setState(State);
                workOrder.setIsValid(isValid);
                workOrder.setRemark(remark);
                workOrderService.update(workOrder);
            }
        }
    }

    @Override
    public void updateTime(List<String> workOrderIds, Integer state) {
        List<List<String>> works = ListUtils.partition(workOrderIds, 900);
        for (List<String> work : works) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("workOrderIds", StringUtil.getStringListString(work));
            params.put("state", state);
            workOrderDao.updateTime(params);
        }
    }

    @Override
    public List<WorkOrderSta> getGroupByUserId(Integer accountId, Integer userType, Integer accountUserId,
                                               String startTime, String endTime, Integer workType,
                                               List<Integer> regionId, Integer buildType, Integer locationType) {

        /**查询代理商运维账号*/
        List<Integer> accountUserIds = new ArrayList<Integer>();
        /**判断当前账号是不是运维人员*/
        if (roleService.getRoleCode(userType).equals(1)) {
            accountUserIds.add(accountUserId);
        }

        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put("userMainIds", StringUtil.getListString(accountUserIds));
        params.put("workType", workType);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        if (CollUtil.isEmpty(regionId)) {
            params.put("exist", "'exist'");
            regionId = georeGionService.getByAccountUserId(accountUserId);
        } else {
            params.put("exist", null);
        }
        params.put("regionId", StringUtil.getListString(regionId));
        params.put("buildType", buildType);
        params.put("locationType", locationType);
        //LogUtil.info("人员工单类型分组  参数："+params.toString());

        List<WorkOrderSta> dlses = workOrderDao.groupByTime(params);
        //LogUtil.info("人员工单类型分组  结果:"+dlses);

        List<WorkOrderSta> dlsefilters = new ArrayList<WorkOrderSta>();
        if (dlses.size() > 0) {
            for (WorkOrderSta dls : dlses) {
                AccountUser au = accountUserService.getById(dls.getUserMainId());
                if (au != null) {
                    dls.setName(au.getName());
                    dls.setPhone(au.getPhone());
                    dlsefilters.add(dls);
                }
            }
        }
        return dlsefilters;
    }

    @Override
    public void del(String workOrderId) {
        workOrderDao.del(workOrderId);
    }

    @Override
    public List<WorkOrderTypeSta> getGroupByType(Integer accountId, AccountUser accountUser, List<Integer> regionId) {
        Map<String, Object> params = new HashMap<>();
        params.put(DaoParamConstant.accountId, accountId);

        if (roleService.getRoleCode(accountUser.getAccountUserType()).equals(1)) {
            params.put("getUserId", accountUser.getAccountUserId());
        }

        if (CollUtil.isEmpty(regionId)) {
            params.put("exist", "'exist'");
            regionId = georeGionService.getByAccountUserId(accountUser.getAccountUserId());
        } else {
            params.put("exist", null);
        }
        params.put("regionId", StringUtil.getListString(regionId));

        return workOrderFinishingDao.getGroupByType(params);
    }

    @Override
    public void update(WorkOrder workOrder) {
        workOrderDao.update(workOrder);
    }

    @Override
    public List<WorkOrder> getWorkOrderList(WorkOrderQueryReqVO reqVO) {
        return workOrderDao.selectWorkOrderList(reqVO);
    }

    @Override
    public WorkOrderCountRespVO getWorkOrderCount(WorkOrderCountRespVO workOrderCountAll, List<WorkOrder> workOrders) {
        WorkOrderCountRespVO workOrderCount = new WorkOrderCountRespVO();
        workOrders.forEach(workOrder -> workOrderCount.add(workOrderCountAll, workOrder));
        return workOrderCount;
    }


    @Override
    public void updateAuditToInvalidByBusinessNOList(List<Integer> businessNOList, Integer isValid, Integer state, String remark) {
        if (CollUtil.isEmpty(businessNOList)) {
            return; // 为空不用更新
        }
        List<WorkOrder> workOrderList = workOrderService.getByBusinessNOList(businessNOList);

        if (CollUtil.isEmpty(workOrderList)) {
            return; // 为空不用更新
        }

        List<String> workOrderIdList = workOrderList.stream().map(WorkOrder::getWorkOrderId).collect(Collectors.toList());
        workOrderDao.updateAuditToInvalidByBusinessNOList(workOrderIdList, isValid, state, remark);
    }

    @Override
    public List<WorkOrder> getByBusinessNOList(List<Integer> businessNOList) {
        return workOrderDao.selectByBusinessNOList(businessNOList);
    }
}
